package com.bifang.module.file.core.util.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.*;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.file.common.vo.FileInfoVO;
import com.bifang.module.file.core.biz.FileInfoIntegration;
import com.bifang.module.file.common.enums.FileServiceTypeEnum;
import com.bifang.module.file.common.enums.RelationshipTypeEnum;
import com.bifang.module.file.common.enums.ShowFileEnum;
import com.bifang.module.file.common.util.ContentType;
import com.bifang.module.file.common.util.FastDFSClient;
import com.bifang.module.file.common.util.FileDiffUtil;
import com.bifang.module.file.common.vo.FileClassVO;
import com.bifang.module.file.core.util.*;
import com.bifang.module.file.dao.model.FileInfo;
import com.bifang.module.file.dao.model.FileRelationship;
import com.bifang.module.file.dao.service.FileInfoService;
import com.bifang.module.file.dao.service.FileRelationshipService;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;

/** 文件服务工具类 */
@Component
public class FileServiceUtilImpl implements FileServiceUtil {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    // 默认上传类型
    @Value("${system.config.file.default.type}")
    private String defaultType;

    @Value("${system.config.file.uploaderFlag}")
    private Boolean uploaderFlag;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Value("${10086.obs.showHost}")
    private String mShowHost;

    @Autowired private FileFtpUtil fileFtpUtil;
    @Autowired private FileLocalUtil fileLocalUtil;
    @Autowired private FileSftpUtil fileSftpUtil;
    @Autowired private FileInfoIntegration fileInfoIntegration;
    @Autowired private FileFastDfsUtil fileFastDfsUtil;
    @Autowired private FileInfoService fileInfoService;
    @Autowired private AliOssUtil aliOssUtil;
    @Autowired private FileCommonUtil fileCommonUtil;
    @Autowired private FastDFSClient fastDFSClient;
    @Autowired private FileRelationshipService fileRelationshipService;
    @Autowired
    private MobilServiceUtil mobilServiceUtil;
    @Autowired
    private WoCloudServiceUtil woCloudServiceUtil;

    @Override
    public void upload(FileClassVO fileClassVO, FileInfoVO fileInfoVO, MultipartFile file) {
        if (file == null) {
            throw new AppException("文件不能为空");
        }
        if (fileClassVO == null) {
            throw new AppException("文件分类不能为空");
        }
        if (fileInfoVO == null) {
            throw new AppException("文件基础信息不能为空");
        }
        String fileMd5 = FileDiffUtil.getMD5(file);
        fileInfoVO.setFileMd5(fileMd5);
        fileInfoVO.setTableName(fileClassVO.getTableName());
        if (checkFileInfo(fileClassVO, fileInfoVO, fileMd5)) {
            return;
        }
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            fileLocalUtil.upload(file, fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            InputStream inputStream = null;
            Boolean flag = true;
            try {
                inputStream = file.getInputStream();
                flag = fileFtpUtil.upload(inputStream, fileClassVO, fileInfoVO);
            } catch (IOException e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        logger.error("关闭文件流异常：", e);
                    }
                }
            }
            if (!flag) {
                throw new AppException("ftp文件上传失败！");
            }

        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            InputStream inputStream = null;
            Boolean flag = true;
            try {
                inputStream = file.getInputStream();
                flag = fileSftpUtil.upload(inputStream, fileClassVO, fileInfoVO);

            } catch (IOException e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        logger.error("关闭文件流异常：", e);
                    }
                }
            }
            if (!flag) {
                throw new AppException("sftp文件上传失败！");
            }
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            InputStream inputStream = null;
            Boolean flag = true;
            try {
                inputStream = file.getInputStream();
                flag = fileFastDfsUtil.upload(inputStream, fileClassVO, fileInfoVO);

            } catch (IOException e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        logger.error("关闭文件流异常：", e);
                    }
                }
            }
            if (!flag) {
                throw new AppException("fastdfs文件上传失败！");
            }
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = aliOssUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        }else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = mobilServiceUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("移动云上传文件失败", e);
                throw new AppException("移动云上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("移动云对象存储文件上传失败！");
            }
        } else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = woCloudServiceUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("沃云上传文件失败", e);
                throw new AppException("沃云上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("沃云对象存储文件上传失败！");
            }
        }

        else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }

        if (StringUtils.isNotBlank(fileInfoVO.getShowId())) {
            FileInfoVO old = fileInfoIntegration.getFileInfoDetail(fileInfoVO.getShowId());
            this.deleteFile(old);
        }
        // 新增文件信息
        fileInfoIntegration.addFileInfo(fileInfoVO);
    }

    @Override
    public void upload(FileClassVO fileClassVO, FileInfoVO fileInfoVO, byte[] file) {
        if (file == null) {
            throw new AppException("文件不能为空");
        }
        if (fileClassVO == null) {
            throw new AppException("文件分类不能为空");
        }
        if (fileInfoVO == null) {
            throw new AppException("文件基础信息不能为空");
        }
        String fileMd5 = FileDiffUtil.getMD5(file);
        fileInfoVO.setFileMd5(fileMd5);

        if (checkFileInfo(fileClassVO, fileInfoVO, fileMd5)) {
            return;
        }
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        InputStream sbs = new ByteArrayInputStream(file);

        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            fileLocalUtil.upload(file, fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = fileFtpUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败:" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("ftp文件上传失败！");
            }

        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {

                flag = fileSftpUtil.upload(file, fileClassVO, fileInfoVO);

            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败:" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("sftp文件上传失败！");
            }
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = fileFastDfsUtil.upload(file, fileClassVO, fileInfoVO);
            if (!flag) {
                throw new AppException("fastdfs文件上传失败！");
            }
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = aliOssUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = woCloudServiceUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = mobilServiceUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }

        if (StringUtils.isNotBlank(fileInfoVO.getShowId())) {
            FileInfoVO old = fileInfoIntegration.getFileInfoDetail(fileInfoVO.getShowId());
            this.deleteFile(old);
        }
        // 新增文件信息
        fileInfoIntegration.addFileInfo(fileInfoVO);
    }

    @Override
    public void upload(FileClassVO fileClassVO, FileInfoVO fileInfoVO, InputStream in) {
        if (in == null) {
            throw new AppException("文件不能为空");
        }
        if (fileClassVO == null) {
            throw new AppException("文件分类不能为空");
        }
        if (fileInfoVO == null) {
            throw new AppException("文件基础信息不能为空");
        }
        String fileMd5 = FileDiffUtil.getMD5(in);
        fileInfoVO.setFileMd5(fileMd5);
        if (checkFileInfo(fileClassVO, fileInfoVO, fileMd5)) {
            return;
        }
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }

        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            fileLocalUtil.upload(in, fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = fileFtpUtil.upload(in, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        logger.error("关闭文件流异常：", e);
                    }
                }
            }
            if (!flag) {
                throw new AppException("ftp文件上传失败！");
            }

        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = fileSftpUtil.upload(in, fileClassVO, fileInfoVO);

            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        logger.error("关闭文件流异常：", e);
                    }
                }
            }
            if (!flag) {
                throw new AppException("sftp文件上传失败！");
            }
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = fileFastDfsUtil.upload(in, fileClassVO, fileInfoVO);
            if (!flag) {
                throw new AppException("fastdfs文件上传失败！");
            }
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = aliOssUtil.upload(in, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = woCloudServiceUtil.upload(in, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = mobilServiceUtil.upload(in, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }

        if (StringUtils.isNotBlank(fileInfoVO.getShowId())) {
            FileInfoVO old = fileInfoIntegration.getFileInfoDetail(fileInfoVO.getShowId());
            old.setStorageGroup(fileInfoVO.getStorageGroup());
            this.deleteFile(old);
        }
        // 新增文件信息
        fileInfoIntegration.addFileInfo(fileInfoVO);
    }

    @Override
    public void imgCompressUpload(FileClassVO fileClassVO, FileInfoVO fileInfoVO, File file, boolean imgCompressDel) {
        if (file == null) {
            throw new AppException("文件不能为空");
        }
        if (fileClassVO == null) {
            throw new AppException("文件分类不能为空");
        }
        if (fileInfoVO == null) {
            throw new AppException("文件基础信息不能为空");
        }
        String fileMd5 = FileDiffUtil.getMD5(file);
        fileInfoVO.setFileMd5(fileMd5);
        if (checkFileInfo(fileClassVO, fileInfoVO, fileMd5)) {
            return;
        }
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }

        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            fileLocalUtil.upload(file, fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = fileFtpUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("ftp文件上传失败！");
            }

        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = fileSftpUtil.upload(file, fileClassVO, fileInfoVO);

            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("sftp文件上传失败！");
            }
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = fileFastDfsUtil.upload(file, fileClassVO, fileInfoVO);
            if (!flag) {
                throw new AppException("fastdfs文件上传失败！");
            }
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = aliOssUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        }else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = woCloudServiceUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        }  else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            Boolean flag = true;
            try {
                flag = mobilServiceUtil.upload(file, fileClassVO, fileInfoVO);
            } catch (Exception e) {
                logger.error("上传文件失败", e);
                throw new AppException("上传文件失败：" + e.getMessage());
            }
            if (!flag) {
                throw new AppException("云对象存储文件上传失败！");
            }
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }
        FileInfoVO old =null;
        if (StringUtils.isNotBlank(fileInfoVO.getShowId())) {
            old=fileInfoIntegration.getFileInfoDetail(fileInfoVO.getShowId());
            old.setStorageGroup(fileInfoVO.getStorageGroup());
            if(imgCompressDel){
                this.deleteFile(old);
            }else{
                UpdateWrapper<FileInfo> updateWrapper=new UpdateWrapper<>();
                updateWrapper.lambda().eq(FileInfo::getFileId,old.getFileId())
                    .set(FileInfo::getShowId, IdUtil.fastSimpleUUID());
                fileInfoService.update(updateWrapper);
            }
        }

        // 新增文件信息
        fileInfoIntegration.addFileInfo(fileInfoVO);
        if(!imgCompressDel&&old!=null){
            FileRelationship fileRelationship = new FileRelationship();
            fileRelationship.setFileType(RelationshipTypeEnum.type3.getType());
            fileRelationship.setFileId(old.getFileId());
            fileRelationship.setMasterId(fileInfoVO.getFileId());
            fileRelationshipService.saveOrUpdate(fileRelationship);
        }
    }

    @Override
    public void download(
            FileClassVO fileClassVO, FileInfoVO fileInfoVO, HttpServletResponse response) {
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        File file = null;
        boolean flag = true;
        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            file = fileLocalUtil.download(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            file = fileFtpUtil.download(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            file = fileSftpUtil.download(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            if (BoolEnum.TRUE.getType().equals(fileInfoVO.getEncryptionFlag())) {
                file = fileFastDfsUtil.download(fileInfoVO);
            }else {
                fileFastDfsUtil.download(fileInfoVO, response);
                flag = false;
            }
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            aliOssUtil.download(fileInfoVO, response);
            flag = false;
        }  else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            woCloudServiceUtil.download(fileInfoVO, response);
            flag = false;
        } else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            mobilServiceUtil.download(fileInfoVO, response);
            flag = false;
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }
        if (flag) {
            if (file == null) {
                throw new AppException("未找到文件信息");
            }
            BufferedInputStream in = null;
            try {
               String fileName = StringUtils.isNotBlank(fileInfoVO.getFileName())?
                        URLEncoder.encode(fileInfoVO.getFileName(), "utf-8")
                                .replaceAll("%20", "\\+")
                                .replaceAll("%28", "\\(")
                                .replaceAll("%29", "\\)")
                                .replaceAll("%3B", ";")
                                .replaceAll("%40", "@")
                                .replaceAll("%23", "\\#")
                                .replaceAll("%26", "\\&")
                                .replaceAll("%2C", "\\,")
                                .replaceAll("%24", "\\$")
                                .replaceAll("%25", "\\%")
                                .replaceAll("%5E", "\\^")
                                .replaceAll("%3D", "\\=")
                                .replaceAll("%2B", "\\+"):fileInfoVO.getFileMd5()+"."+fileInfoVO.getFileSuffix();
                String contentType = ContentType.getContentType("."+fileInfoVO.getFileSuffix());
                if(contentType==null){
                    contentType = ContentType.getContentType(fileInfoVO.getFileSuffix());
                }
                response.setCharacterEncoding("utf-8");
                response.setContentType(contentType);
                response.addHeader("Content-Length", "" + file.length());
                if (ShowFileEnum.getByType(contentType) != null) {
                    final String charset = ObjectUtil.defaultIfNull(response.getCharacterEncoding(), CharsetUtil.UTF_8);
                    response.setHeader("Content-Disposition", StrUtil.format("inline;filename=\"{}\"",
                            URLUtil.encode(fileName, CharsetUtil.charset(charset))));
                } else {
                    response.setContentType("application/octet-stream;charset=utf-8");
                    final String charset = ObjectUtil.defaultIfNull(response.getCharacterEncoding(), CharsetUtil.UTF_8);
                    response.setHeader("Content-Disposition", StrUtil.format("attachment;filename=\"{}\"",
                            URLUtil.encode(fileName, CharsetUtil.charset(charset))));
                }
                response.setContentLengthLong(fileInfoVO.getFileSize());
                in = FileUtil.getInputStream(file);


                ServletUtil.write(response, in);
            }catch (Exception e){
                logger.error("文件下载输出异常",e);
            }finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                FileUtil.del(file);
            }
        }
    }

    @Override
    public String getBase64(FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        String base64 = "";
        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = fileLocalUtil.getBase64(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = fileFtpUtil.getBase64(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = fileSftpUtil.getBase64(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = fileFastDfsUtil.getBase64(fileInfoVO);
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = aliOssUtil.getBase64(fileInfoVO);
        }  else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = woCloudServiceUtil.getBase64(fileInfoVO);
        } else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            base64 = mobilServiceUtil.getBase64(fileInfoVO);
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }
        if (StringUtils.isBlank(base64)) {
            throw new AppException("未找到文件信息");
        }
        return base64;
    }

    @Override
    public void showFile(FileInfoVO fileInfoVO, HttpServletResponse response,Boolean isSendRedirect) {
        String fileServiceType = fileInfoVO.getFileServiceType();
        String path = "";
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            // fileLocalUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            // fileFtpUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            // fileSftpUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            path = fileFastDfsUtil.show(fileInfoVO, response);
            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            try {
                fileName =
                        URLEncoder.encode(fileInfoVO.getFileName(), "utf-8")
                                .replaceAll("%20", "\\+")
                                .replaceAll("%28", "\\(")
                                .replaceAll("%29", "\\)")
                                .replaceAll("%3B", ";")
                                .replaceAll("%40", "@")
                                .replaceAll("%23", "\\#")
                                .replaceAll("%26", "\\&")
                                .replaceAll("%2C", "\\,")
                                .replaceAll("%24", "\\$")
                                .replaceAll("%25", "\\%")
                                .replaceAll("%5E", "\\^")
                                .replaceAll("%3D", "\\=")
                                .replaceAll("%2B", "\\+");
                path =
                        URLEncoder.encode(path, "utf-8")
                                .replaceAll("%20", "\\+")
                                .replaceAll("%28", "\\(")
                                .replaceAll("%29", "\\)")
                                .replaceAll("%3B", ";")
                                .replaceAll("%40", "@")
                                .replaceAll("%23", "\\#")
                                .replaceAll("%26", "\\&")
                                .replaceAll("%2C", "\\,")
                                .replaceAll("%24", "\\$")
                                .replaceAll("%25", "\\%")
                                .replaceAll("%5E", "\\^")
                                .replaceAll("%3D", "\\=")
                                .replaceAll("%2B", "\\+");
            } catch (UnsupportedEncodingException e) {
                logger.error("系统异常:", e);
            }
            response.setHeader("X-Accel-Redirect", path);
            // attachment;
            String contentType = ContentType.getContentType("."+fileInfoVO.getFileSuffix());
            if(contentType==null){
                contentType = ContentType.getContentType(fileInfoVO.getFileSuffix());
            }
            response.setCharacterEncoding("utf-8");
            response.setContentType(contentType);
            if (ShowFileEnum.getByType(contentType) != null) {
                response.setHeader("Content-Disposition", "inline;filename=\"" + fileName + "\"");
            } else {
                response.setHeader(
                        "Content-Disposition", "attachment;filename=\"" + fileName + "\"");
            }
            response.setContentLengthLong(fileInfoVO.getFileSize());

        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            /**
            String urlString=aliOssUtil.getUrl(fileInfoVO);
            System.out.println(urlString);
            String query="";
            try {
                URL url = new URL(urlString);
                query = url.getQuery();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("阿里url地址解析异常"+e.getMessage());
            }
             **/
             path = "/aliOSS/" +fileInfoVO.getFilePath();
             /**
            if(StringUtils.isNotBlank(query)){
                path = path+"?"+query;
            }
            System.out.println(path);
             **/

            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            try {
                fileName =
                        URLEncoder.encode(fileInfoVO.getFileName(), "utf-8")
                                .replaceAll("%20", "\\+")
                                .replaceAll("%28", "\\(")
                                .replaceAll("%29", "\\)")
                                .replaceAll("%3B", ";")
                                .replaceAll("%40", "@")
                                .replaceAll("%23", "\\#")
                                .replaceAll("%26", "\\&")
                                .replaceAll("%2C", "\\,")
                                .replaceAll("%24", "\\$")
                                .replaceAll("%25", "\\%")
                                .replaceAll("%5E", "\\^")
                                .replaceAll("%3D", "\\=")
                                .replaceAll("%2B", "\\+");

            } catch (UnsupportedEncodingException e) {
                logger.error("系统异常:", e);
            }
            response.setHeader("X-Accel-Redirect", path);
            // attachment;
            String contentType = ContentType.getContentType("."+fileInfoVO.getFileSuffix());
            if(contentType==null){
                contentType = ContentType.getContentType(fileInfoVO.getFileSuffix());
            }
            response.setCharacterEncoding("utf-8");
            response.setContentType(contentType);
            if (ShowFileEnum.getByType(contentType) != null) {
                response.setHeader("Content-Disposition", "filename=\"" + fileName + "\"");
            } else {
                response.setHeader(
                        "Content-Disposition", "attachment;filename=\"" + fileName + "\"");
            }
            response.setContentLengthLong(fileInfoVO.getFileSize());
        } else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            if(isSendRedirect){//浏览器重定向
                String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
                try {
                    fileName =
                            URLEncoder.encode(fileInfoVO.getFileName(), "utf-8")
                                    .replaceAll("%20", "\\+")
                                    .replaceAll("%28", "\\(")
                                    .replaceAll("%29", "\\)")
                                    .replaceAll("%3B", ";")
                                    .replaceAll("%40", "@")
                                    .replaceAll("%23", "\\#")
                                    .replaceAll("%26", "\\&")
                                    .replaceAll("%2C", "\\,")
                                    .replaceAll("%24", "\\$")
                                    .replaceAll("%25", "\\%")
                                    .replaceAll("%5E", "\\^")
                                    .replaceAll("%3D", "\\=")
                                    .replaceAll("%2B", "\\+");

                } catch (UnsupportedEncodingException e) {
                    logger.error("系统异常:", e);
                }
                String contentType = ContentType.getContentType("."+fileInfoVO.getFileSuffix());
                if(contentType==null){
                    contentType = ContentType.getContentType(fileInfoVO.getFileSuffix());
                }
                response.setCharacterEncoding("utf-8");
                response.setContentType(contentType);
                if (ShowFileEnum.getByType(contentType) != null) {
                    response.setHeader("Content-Disposition", "inline;filename=\"" + fileName + "\"");
                } else {
                    response.setHeader(
                            "Content-Disposition", "attachment;filename=\"" + fileName + "\"");
                }
                response.setContentLengthLong(fileInfoVO.getFileSize());
                try {
                    response.sendRedirect(mShowHost+"/"+fileInfoVO.getFilePath());
                } catch (IOException e) {
                    logger.error("重定向失败",e);
                }
            }else {//通过nginx转发
                path = "/mobileOSS/" +fileInfoVO.getFilePath();
                response.setHeader("X-Accel-Redirect", path);
                String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
                try {
                    fileName =
                            URLEncoder.encode(fileInfoVO.getFileName(), "utf-8")
                                    .replaceAll("%20", "\\+")
                                    .replaceAll("%28", "\\(")
                                    .replaceAll("%29", "\\)")
                                    .replaceAll("%3B", ";")
                                    .replaceAll("%40", "@")
                                    .replaceAll("%23", "\\#")
                                    .replaceAll("%26", "\\&")
                                    .replaceAll("%2C", "\\,")
                                    .replaceAll("%24", "\\$")
                                    .replaceAll("%25", "\\%")
                                    .replaceAll("%5E", "\\^")
                                    .replaceAll("%3D", "\\=")
                                    .replaceAll("%2B", "\\+");

                } catch (UnsupportedEncodingException e) {
                    logger.error("系统异常:", e);
                }
                // attachment;
                String contentType = ContentType.getContentType("."+fileInfoVO.getFileSuffix());
                if(contentType==null){
                    contentType = ContentType.getContentType(fileInfoVO.getFileSuffix());
                }
                response.setCharacterEncoding("utf-8");
                response.setContentType(contentType);
                if (ShowFileEnum.getByType(contentType) != null) {
                    response.setHeader("Content-Disposition", "inline;filename=\"" + fileName + "\"");
                } else {
                    response.setHeader(
                            "Content-Disposition", "attachment;filename=\"" + fileName + "\"");
                }
                response.setContentLengthLong(fileInfoVO.getFileSize());
            }
        }else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {

             String urlString=woCloudServiceUtil.getUrl(fileInfoVO);
             System.out.println(urlString);
             String query="";
             try {
             URL url = new URL(urlString);
             query = url.getQuery();
             } catch (Exception e) {
             e.printStackTrace();
             logger.error("阿里url地址解析异常"+e.getMessage());
             }

            path = "/woCloudOSS/" +fileInfoVO.getFilePath();

             if(StringUtils.isNotBlank(query)){
             path = path+"?"+query;
             }
             System.out.println(path);


            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            try {
                fileName =
                        URLEncoder.encode(fileInfoVO.getFileName(), "utf-8")
                                .replaceAll("%20", "\\+")
                                .replaceAll("%28", "\\(")
                                .replaceAll("%29", "\\)")
                                .replaceAll("%3B", ";")
                                .replaceAll("%40", "@")
                                .replaceAll("%23", "\\#")
                                .replaceAll("%26", "\\&")
                                .replaceAll("%2C", "\\,")
                                .replaceAll("%24", "\\$")
                                .replaceAll("%25", "\\%")
                                .replaceAll("%5E", "\\^")
                                .replaceAll("%3D", "\\=")
                                .replaceAll("%2B", "\\+");

            } catch (UnsupportedEncodingException e) {
                logger.error("系统异常:", e);
            }
            response.setHeader("X-Accel-Redirect", path);
            // attachment;
            String contentType = ContentType.getContentType("."+fileInfoVO.getFileSuffix());
            if(contentType==null){
                contentType = ContentType.getContentType(fileInfoVO.getFileSuffix());
            }
            response.setCharacterEncoding("utf-8");
            response.setContentType(contentType);
            if (ShowFileEnum.getByType(contentType) != null) {
                response.setHeader("Content-Disposition", "filename=\"" + fileName + "\"");
            } else {
                response.setHeader(
                        "Content-Disposition", "attachment;filename=\"" + fileName + "\"");
            }
            response.setContentLengthLong(fileInfoVO.getFileSize());
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }
    }

    @Override
    public void deleteFile(FileInfoVO fileInfoVO) {
        String fileServiceType = fileInfoVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            fileLocalUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            fileFtpUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            fileSftpUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            fileFastDfsUtil.delete(fileInfoVO);
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            aliOssUtil.deleteFile(fileInfoVO);
        }  else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            woCloudServiceUtil.deleteFile(fileInfoVO);
        } else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            mobilServiceUtil.deleteFile(fileInfoVO);
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }
        // 删除文件信息
        fileInfoIntegration.deleteFileInfo(fileInfoVO.getFileId(),fileInfoVO.getTableName(),fileInfoVO.getShowId());
    }

    @Override
    public void imgCompress(FileInfoVO fileInfoVO,FileClassVO fileClassVO) {

        //获取图片
        String fileServiceType = fileClassVO.getFileServiceType();
        if (StringUtils.isBlank(fileServiceType)) {
            fileServiceType = defaultType;
        }
        InputStream fromPic = null;
        boolean flag = true;
        File file=null;
        if (FileServiceTypeEnum.LOCAL.getType().equalsIgnoreCase(fileServiceType)) {
            file=fileLocalUtil.download(fileClassVO, fileInfoVO);

        } else if (FileServiceTypeEnum.FTP.getType().equalsIgnoreCase(fileServiceType)) {
            file=fileFtpUtil.download(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.SFTP.getType().equalsIgnoreCase(fileServiceType)) {
            file=fileSftpUtil.download(fileClassVO, fileInfoVO);
        } else if (FileServiceTypeEnum.FASTDFS.getType().equalsIgnoreCase(fileServiceType)) {
            if (BoolEnum.TRUE.getType().equals(fileInfoVO.getEncryptionFlag())) {
                file = fileFastDfsUtil.download(fileInfoVO);
            }else{
                fromPic = fastDFSClient.download(fileInfoVO.getStorageGroup(), fileInfoVO.getFilePath());
                flag=false;
            }
        } else if (FileServiceTypeEnum.ALIOSS.getType().equalsIgnoreCase(fileServiceType)) {
            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            file= fileCommonUtil.createTempFileDownload(fileName);
            aliOssUtil.download(fileInfoVO, file);
        } else if (FileServiceTypeEnum.WOCLOUDOSS.getType().equalsIgnoreCase(fileServiceType)) {
            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            file= fileCommonUtil.createTempFileDownload(fileName);
            woCloudServiceUtil.download(fileInfoVO, file);
        }else if (FileServiceTypeEnum.MOBILEOSS.getType().equalsIgnoreCase(fileServiceType)) {
            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            file= fileCommonUtil.createTempFileDownload(fileName);
            mobilServiceUtil.download(fileInfoVO, file);
        } else {
            throw new AppException("文件服务器类型不存在（" + fileServiceType + "）");
        }
        if(flag){
            if(file==null){
                return;
            }
            fromPic = FileUtil.getInputStream(file);
        }
        if(fromPic==null){
            return;
        }
        String toFileName = fileInfoVO.getFileMd5()+".compress.jpg";
        File toPic= fileCommonUtil.createTempFileDownload(toFileName);
        //压缩
        try {
            //图片尺寸不变，压缩图片文件大小outputQuality实现,参数1为最高质量
            Thumbnails.of(fromPic).scale(1f).outputQuality(0.35f).outputFormat("jpg").toFile(toPic);
        }catch (Exception e){
            logger.error("图片压缩失败:",e);
            return;
        }finally {
            if(file!=null){
                FileUtil.del(file);
            }
            if(fromPic!=null){
                try {
                    fromPic.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //重新上传
        if(toPic==null||toPic.length() <= 0){
            return;
        }
        Boolean imgCompressDel=fileInfoVO.getImgCompressDel();
        if(imgCompressDel==null){
            imgCompressDel=true;
        }
        fileInfoVO.setFileSuffix("jpg");
        fileInfoVO.setFileName(toFileName);
        fileInfoVO.setFileSize(null);
        this.imgCompressUpload(fileClassVO,fileInfoVO,toPic,imgCompressDel);
        //删除本地图片
        if(toPic!=null){
            FileUtil.del(toPic);
        }
    }

    /** 设置文件信息 */
    private void setFileInfo(FileInfoVO fileInfoVO, File file) {
        if (StringUtils.isBlank(fileInfoVO.getFileName())) {
            fileInfoVO.setFileName(file.getName());
        }
        if (StringUtils.isBlank(fileInfoVO.getFileSuffix())) {
            fileInfoVO.setFileSuffix(FileUtil.getType(file));
        }
        if (fileInfoVO.getFileSize() == null) {
            fileInfoVO.setFileSize(FileUtil.size(file));
        }
    }

    /** 备注：同文件，不同文件名新增file_info数据 */
    private Boolean checkFileInfo(FileClassVO fileClassVO, FileInfoVO fileInfoVO, String fileMd5) {
        // 判断文件是否存在
        Boolean retflag = true;
        if (fileInfoVO.getForceFlag() == null) {
            fileInfoVO.setForceFlag(false);
        }
        // 是否根据上传人设置
        if (fileInfoVO.getUploaderFlag() == null) {
            if (uploaderFlag == null) {
                fileInfoVO.setUploaderFlag(false);
            } else {
                fileInfoVO.setUploaderFlag(uploaderFlag);
            }
        }
        if (fileInfoVO.getForceFlag()) {
            retflag = false;
            return retflag;
        }
        QueryWrapper<FileInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(FileInfo::getFileMd5, fileMd5)
                .eq(FileInfo::getFileClassCode, fileInfoVO.getFileClassCode())
                .eq(FileInfo::getUpAppId, fileInfoVO.getUpAppId());
        if (fileInfoVO.getUploaderFlag()) {
            if (StringUtils.isNotBlank(fileInfoVO.getUploaderId())) {
                queryWrapper.lambda().eq(FileInfo::getUploaderId, fileInfoVO.getUploaderId());
            }
        }

        List<FileInfo> fileInfoList = fileInfoService.list(queryWrapper);

        if (!CollectionUtils.isEmpty(fileInfoList)) {
            FileInfo old = null;
            Boolean flag = true;
            for (FileInfo fileInfo : fileInfoList) {
                old = fileInfo;
                if (fileInfo.getFileName().equals(fileInfoVO.getFileName())) {
                    // 相同客户端，相同文件名，相同文件内容，相同分类，则直接返回
                    BeanUtil.copyProperties(fileInfo, fileInfoVO);
                    flag = false;
                    break;
                }
            }
            if (flag) {
                // 相同客户端，相同文件内容，相同分类，则保持新数据指向原文件
                fileInfoVO.setEncryptionFlag(old.getEncryptionFlag());
                fileInfoVO.setFilePassowrd(old.getFilePassowrd());
                fileInfoVO.setFilePath(old.getFilePath());
                fileInfoVO.setFileSize(old.getFileSize());
                fileInfoIntegration.addFileInfo(fileInfoVO);
            }

        } else {
            retflag = false;
        }
        return retflag;
    }

    public Boolean checkImg(MultipartFile file) {
        Boolean flag = false;
        try {
            BufferedImage image = ImageIO.read(file.getInputStream());
            if (image == null) {
                flag = false;
            } else {
                flag = true;
            }
        } catch (IOException e) {
            flag = false;
        }
        return flag;
    }

    public Boolean checkImg(InputStream inputStream) {
        Boolean flag = false;
        try {
            BufferedImage image = ImageIO.read(inputStream);
            if (image == null) {
                flag = false;
            } else {
                flag = true;
            }
        } catch (IOException e) {
            flag = false;
        }
        return flag;
    }
}
